package com.jumper.study.front.service.impl;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jumper.study.common.util.StrUtil;
import com.jumper.study.db.dao.LessonChapterMapper;
import com.jumper.study.db.dao.LessonEbookMapper;
import com.jumper.study.db.dao.StudentLessonMapper;
import com.jumper.study.db.dao.StudentStudyLogMapper;
import com.jumper.study.db.dto.StudentLessonChapterDto;
import com.jumper.study.db.dto.StudentLessonStudyDto;
import com.jumper.study.db.dto.StudyTimeDto;
import com.jumper.study.db.model.LessonEbook;
import com.jumper.study.db.model.StudentLesson;
import com.jumper.study.db.model.StudentStudyLog;
import com.jumper.study.front.dto.req.MyLessonSearchReq;
import com.jumper.study.front.dto.resp.LessonEbookResp;
import com.jumper.study.front.dto.resp.MyLessonChapterResp;
import com.jumper.study.front.dto.resp.MyLessonListItemResp;
import com.jumper.study.front.dto.vo.PageVO;
import com.jumper.study.front.service.StudentLessonService;


@Service("frontStudentLessonService")
public class StudentLessonServiceImpl implements StudentLessonService {
    private static final String STUDY_KEY = "FRONT_SLSERVICE_";

    private static final Integer reConnectExpire = 30;  //重连后是否能接回原记录的超时时间

    @Autowired
    private StudentLessonMapper slMapper; 

    @Autowired
    private StudentStudyLogMapper studyMapper;

    @Autowired
    private LessonEbookMapper ebookMapper;

    @Autowired
    private LessonChapterMapper chapterMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public boolean isBuyed(Long lessonId, Long accountId) {
        LambdaQueryWrapper<StudentLesson> query = Wrappers.lambdaQuery();
        query.eq(StudentLesson::getAccountId, accountId);
        query.eq(StudentLesson::getLessonId, lessonId);

        return slMapper.exists(query);
    }

    @Override
    public List<MyLessonListItemResp> pageSearchList(PageVO page, MyLessonSearchReq search) {
        Page<StudentLessonStudyDto> p = Page.of(page.getPage(), page.getPageSize());
        List<StudentLessonStudyDto> lessons = slMapper.pageListWithLesson(p, search.getAccountId(), search.getExpired()).getRecords();
        page.setTotal(p.getTotal());

        return lessons.stream().map(l -> {
            MyLessonListItemResp item = new MyLessonListItemResp();
            item.setId(l.getId());
            item.setTitle(l.getTitle());
            item.setThumb(l.getThumb());
            item.setChapterTitle(l.getChapterTitle());
            item.setTotalDuration(l.getTotalDuration());
            item.setStudyTimes(l.getStudyTimes());
            item.setChapterId(l.getChapterId());
            return item;
        }).toList();
    }

    @Override
    public List<MyLessonChapterResp> chapters(Long lessonId, Long accountId) {
        LambdaQueryWrapper<StudentLesson> slQuery = Wrappers.lambdaQuery();
        slQuery.eq(StudentLesson::getLessonId, lessonId);
        slQuery.eq(StudentLesson::getAccountId, accountId);
        StudentLesson entity = slMapper.selectOne(slQuery);
        if (entity == null) {
            return new ArrayList<>(0);
        }

        List<StudentLessonChapterDto> chapters = chapterMapper.listWithStudyTimes(lessonId, accountId);
        return chapters.stream().map(c -> {
            MyLessonChapterResp item = new MyLessonChapterResp();
            item.setId(c.getId());
            item.setTitle(c.getTitle());
            item.setDuration(c.getDuration());
            item.setVideo(c.getVideo());
            item.setStudyTimes(c.getStudyTimes());
            return item;
        }).toList();
    }

    @Override
    public List<LessonEbookResp> ebooks(Long lessonId, Long accountId) {
        LambdaQueryWrapper<StudentLesson> slQuery = Wrappers.lambdaQuery();
        slQuery.eq(StudentLesson::getLessonId, lessonId);
        slQuery.eq(StudentLesson::getAccountId, accountId);
        StudentLesson entity = slMapper.selectOne(slQuery);
        if (entity == null) {
            return new ArrayList<>(0);
        }

        LambdaQueryWrapper<LessonEbook> query = Wrappers.lambdaQuery();
        query.eq(LessonEbook::getLessonId, lessonId);
        query.orderByAsc(LessonEbook::getSort);
        List<LessonEbook> ebooks = ebookMapper.selectList(query);

        return ebooks.stream().map(e -> {
            LessonEbookResp item = new LessonEbookResp();
            item.setId(e.getId());
            item.setFile(e.getFile());
            item.setTitle(e.getTitle());
            item.setSize(0l);
            return item;
        }).toList();
    }

    @Override
    public boolean startStudy(Long lessonId, Long chapterId, Long accountId) {
        if (lessonId <= 0 || chapterId <= 0 || accountId <= 0) {
            return false;
        }
        StudentStudyLog study = new StudentStudyLog();
        study.setAccountId(accountId);
        study.setChapterId(chapterId);
        study.setLessonId(lessonId);
        int ret = studyMapper.insert(study);
        if (ret <= 0) {
            return false;
        }

        String key = STUDY_KEY + accountId + "_" + lessonId + "_" + chapterId;
        redisTemplate.opsForValue().set(key, study.getId().toString());
        redisTemplate.expire(key, reConnectExpire, TimeUnit.SECONDS);
        return true;
        // StudentStudyLog study = new StudentStudyLog();
        // study.setAccountId(accountId);
        // study.setChapterId(chapterId);
        // study.setLessonId(lessonId);
        // int ret = studyMapper.insert(study);

        // if (ret > 0) {
        //     LambdaUpdateWrapper<StudentLesson> updateWrapper = Wrappers.lambdaUpdate();
        //     updateWrapper.set(StudentLesson::getChapterId, chapterId);
        //     updateWrapper.eq(StudentLesson::getAccountId, accountId);
        //     updateWrapper.eq(StudentLesson::getLessonId, lessonId);
        //     ret = slMapper.update(updateWrapper);
        // }
        // return SqlHelper.retBool(ret);
    }

    @Override
    public void updateStudy(Long lessonId, Long chapterId, Long accountId) {
        String key = STUDY_KEY + accountId + "_" + lessonId + "_" + chapterId;
        String value = redisTemplate.opsForValue().get(key);
        if (StrUtil.isEmpty(value)) {
            return;
        }
        redisTemplate.expire(key, reConnectExpire, TimeUnit.SECONDS);

        // StudentStudyLog study = getLastStudy(lessonId, chapterId, accountId);
        // if (study == null) {
        //     return;
        // }

        // LambdaUpdateWrapper<StudentStudyLog> updateWrapper = Wrappers.lambdaUpdate();
        // updateWrapper.set(StudentStudyLog::getLeaveTime, LocalDateTime.now());
        // updateWrapper.eq(StudentStudyLog::getId, study.getId());
        // studyMapper.update(updateWrapper);
    }

    @Override
    @Transactional
    public void endStudy(Long lessonId, Long chapterId, Long accountId) {
        String key = STUDY_KEY + accountId + "_" + lessonId + "_" + chapterId;
        String strId = redisTemplate.opsForValue().get(key);
        redisTemplate.delete(key);
        if (StrUtil.isEmpty(strId)) {
            return;
        }
        Long id = Long.parseLong(strId);
        StudentStudyLog study = studyMapper.selectById(id);
        if (study == null) {
            return;
        }
        study.setLeaveTime(LocalDateTime.now());
        studyMapper.updateById(study);

        //更新学习时长
        StudyTimeDto value = studyMapper.selectStudyTimes(accountId, lessonId);
        LambdaUpdateWrapper<StudentLesson> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.set(StudentLesson::getStudyTimes, value.getStudyTimes());
        updateWrapper.eq(StudentLesson::getAccountId, accountId);
        updateWrapper.eq(StudentLesson::getLessonId, lessonId);
        slMapper.update(updateWrapper);
    }

    @Override
    public boolean reConnect(Long lessonId, Long chapterId, Long accountId) {
        String key = STUDY_KEY + accountId + "_" + lessonId + "_" + chapterId;
        String strId = redisTemplate.opsForValue().get(key);
        if (StrUtil.isEmpty(strId)) {
            return false;
        }
        return true;
        // StudentStudyLog study = getLastStudy(lessonId, chapterId, accountId);
        // if (study == null) {
        //     return false;
        // }
        // Duration duration = Duration.between(LocalDateTime.now(), study.getLeaveTime());
        // if (duration.toSeconds() > reConnectExpire) {   //重连超时
        //     return false;
        // }

        // //重连成功
        // LambdaUpdateWrapper<StudentStudyLog> updateWrapper = Wrappers.lambdaUpdate();
        // updateWrapper.set(StudentStudyLog::getLeaveTime, LocalDateTime.now());
        // updateWrapper.eq(StudentStudyLog::getId, study.getId());
        // studyMapper.update(updateWrapper);
        // return true;
    }
    
    /*private StudentStudyLog getLastStudy(Long lessonId, Long chapterId, Long accountId) {
        LambdaQueryWrapper<StudentStudyLog> query = Wrappers.lambdaQuery();
        query.eq(StudentStudyLog::getAccountId, accountId);
        query.eq(StudentStudyLog::getLessonId, lessonId);
        query.eq(StudentStudyLog::getChapterId, chapterId);
        query.orderByDesc(StudentStudyLog::getId);

        return studyMapper.selectOne(query);
    }*/

    @Override
    public Long studyTimes(Long accountId, Long lessonId) {
        StudyTimeDto dto = studyMapper.selectStudyTimes(accountId, lessonId);
        return dto.getStudyTimes();
    }
}
